package com.jstarcraft.ai.jsat.classifiers.evaluation;

/**
 * The F<sub>&beta;</sub> score is the generalization of {@link F1Score}, where
 * &beta; indicates the level of preference for precision over recall. This
 * score is only valid for binary classification problems.
 * 
 * @author Edward Raff
 */
public class FbetaScore extends SimpleBinaryClassMetric {

    private static final long serialVersionUID = -7530404462591303694L;
    private double beta;

    /**
     * Creates a new F<sub>&beta;</sub> score
     * 
     * @param beta the weight to apply to precision over recall, must be in (0,
     *             &infin;)
     */
    public FbetaScore(double beta) {
        super();
        if (beta <= 0 || Double.isInfinite(beta) || Double.isNaN(beta))
            throw new IllegalArgumentException("beta must be in (0, inf), not " + beta);
        this.beta = beta;
    }

    /**
     * Copy constructor
     * 
     * @param toClone the object to copy
     */
    public FbetaScore(FbetaScore toClone) {
        super(toClone);
        this.beta = toClone.beta;
    }

    @Override
    public double getScore() {
        final double betaSqrd = beta * beta;
        return (1 + betaSqrd) * tp / ((1 + betaSqrd) * tp + fp + betaSqrd * fn);
    }

    @Override
    public boolean equals(Object obj) {
        if (this.getClass().isAssignableFrom(obj.getClass()) && obj.getClass().isAssignableFrom(this.getClass())) {
            return this.beta == ((FbetaScore) obj).beta;
        }
        return false;
    }

    @Override
    public int hashCode() {
        return new Double(beta).hashCode();
    }

    @Override
    public FbetaScore clone() {
        return new FbetaScore(this);
    }

    @Override
    public String getName() {
        return "F beta(" + beta + ") Score";
    }

}
